#ifndef _SLEIPNER_WIIMOTE_H_
#define _SLEIPNER_WIIMOTE_H_

#include "../sleipner_config.h"
#include <vector>
namespace input
{

class	WiimoteAbstract
{
public:
			WiimoteAbstract() 	{};
	virtual ~WiimoteAbstract() 	{};
	virtual void				Init()= 0;
	virtual void				Shutdown()= 0;
	virtual void				Tick(float dt)= 0;
	virtual void				StartRumble(int ControllerID) = 0;
	virtual void				StopRumble(int ControllerID) = 0;
};

class WiimoteListener;
class	Wiimote

{
public:
	static const int		MAX_WIIMOTE = 4;
	static const int		MAX_SAMPLE_RANGE = 512;	// +/- for acceleration
	enum		BUTTON_ID
	{
		BUTTON_UP,
		BUTTON_DOWN,
		BUTTON_LEFT,
		BUTTON_RIGHT,
		BUTTON_A,
		BUTTON_B,
		BUTTON_Z,
		BUTTON_1,
		BUTTON_2,
		BUTTON_PLUS,
		BUTTON_MINUS,
		BUTTON_MENU,
		BUTTON_START,
		BUTTON_C
	};
	struct			Button
	{
		BUTTON_ID		ID;
		bool			IsDown;
		bool			IsChanged;
		float			ClickTime;
	};

	static Wiimote&	Instance();

	void			Tick(float dt);
	bool			IsDown(int	Controller, BUTTON_ID ID);
	bool			IsPressed(int	Controller, BUTTON_ID ID);
	bool			IsReleased(int	Controller, BUTTON_ID ID);
	void			GetAcceleration(int	Controller, float& x, float& y, float& z);

	// informational updates
	void			ButtonUpdate(int	ControllerID, BUTTON_ID ID, bool IsDown);
	void			AccelerationUpdate(int	ControllerID, float x, float y, float z);

	// get accel info?
// listener functions
	void						AddListener(WiimoteListener* _pListener)
	{
		m_Listeners.push_back(_pListener);
	}
	void						DropListener(WiimoteListener* _pListener)
	{
		for (unsigned int i=0; i<m_Listeners.size(); i++)
		{
			if (m_Listeners[i] == _pListener)
			{
				m_Listeners.erase(m_Listeners.begin()+i);
			}
		}
	}

	// void feedback systems
	void			StartRumble(int ControllerID, float Time);
	void			StopRumble(int ControllerID);

private:
	Wiimote();
	~Wiimote();
	void			Init();
	void			Shutdown();
	struct			Controller
	{
		Button				ButtonA[BUTTON_C];
		float				AccX, AccY, AccZ;
		float				RumbleTime;
	};
	Controller						m_ControllerA[MAX_WIIMOTE];
	// provide listeners later
	std::vector<WiimoteListener*>	m_Listeners;

	WiimoteAbstract*				m_Ctrl;

};

class	WiimoteListener
{
public:
	/// will automatically register itself with the keyboard handler
						WiimoteListener();
	/// will automatically de-register itself with the keyboard handler
	virtual				~WiimoteListener();
	/// key was pressed this frame
	virtual	void		WiiButtonPressed(int WiimoteID, Wiimote::Button* pButton) {};
	virtual	void		WiiButtonReleased(int WiimoteID, Wiimote::Button* pButton) {};
	virtual	void		WiiButtonDown(int WiimoteID, Wiimote::Button* pButton) {};

	/// key was pressed this frame
	virtual	void		WiiAcceleration(int WiimoteID, float x, float y, float z) {};

	void				Disable()	{ m_IsEnabled = false; };
	void				Enable()	{ m_IsEnabled = true; };
	bool				IsEnabled() const { return m_IsEnabled; };
public:
	bool				m_IsEnabled;
};

}
#define GET_WIIMOTE() input::Wiimote::Instance()

#endif // _SLEIPNER_WIIMOTE_H_
